package com.inspur.security.cbb3.kms.config.security;

import com.inspur.security.cbb3.kms.enums.SystemCode;
import com.inspur.security.cbb3.kms.login.service.LoginAttemptService;
import com.inspur.security.cbb3.kms.sysuser.service.SysUserService;
import com.inspur.security.cbb3.kms.sysuser.vo.SysUserDetail;
import com.inspur.security.cbb3.kms.utils.IpUtil;
import com.inspur.security.cbb3.kms.utils.JwtUtils;
import com.inspur.security.cbb3.kms.utils.RedisUtil;
import com.inspur.security.cbb3.kms.utils.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Filter base class:1.IP锁定校验 2.验证token有效性
 * @author lijunchang
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Value("${jwt.header}")
    private String header;

    @Value("${jwt.tokenHead}")
    private String tokenHeader;

    @Value("${jwt.overTime}")
    private String overTime = "600";

    @Resource
    private JwtUtils jwtUtils;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private JwtUtils jwtTokenUtil;

    @Autowired
    private LoginAttemptService loginAttemptService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    	if (loginAttemptService.isBlocked(IpUtil.getRemoteHost(request))) {
    		chain.doFilter(request, response);
    		return;
        }

    	String authToken = request.getHeader(this.header);
    	if(authToken==null) {
    		authToken=request.getParameter(this.header);
    	}
        if (StringUtils.isNotEmpty(authToken) && authToken.startsWith(this.tokenHeader)) {
            authToken = authToken.substring(this.tokenHeader.length());
        } else {
            // 不按规范,不允许通过验证
            authToken = null;
        }
        String username = jwtUtils.getUsernameFromToken(authToken);
        if (jwtUtils.containToken(username, authToken) && username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            SysUserDetail userDetail = jwtUtils.getUserFromToken(authToken);
            if (jwtUtils.validateToken(authToken, userDetail)) {
                //长时间未操作校验
                //获取缓存K（token）
                String cacheToken = String.valueOf(redisUtil.get(authToken));
                if (StringUtils.isNotEmpty(cacheToken) && !"null".equalsIgnoreCase(cacheToken)){
                    //刷新有效期
                    redisUtil.set(authToken,authToken,Integer.parseInt(overTime));
                }else {
                    //长时间未操作，退出登录
                    String userName = jwtTokenUtil.getUsernameFromToken(authToken);
                    jwtTokenUtil.deleteToken(userName);
                    ServletUtil.returnException(response, SystemCode.ERR_LOGIN_OVERTIME, HttpStatus.REQUEST_TIMEOUT);
                    return;
                }
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetail, null, userDetail.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        chain.doFilter(request, response);
    }
}
